package com.kxf.androidtestdemo.activity

import android.os.Bundle
import android.util.Log
import android.view.View
import com.kxf.androidtestdemo.R
import com.kxf.androidtestdemo.adapter.MyDexClassLoader
import com.kxf.androidtestdemo.util.FileUtils
import java.io.File
import java.io.IOException
import java.lang.ref.WeakReference

class DexLoaderActivity : BaseActivity() {
    var reference: WeakReference<Class<*>>? = null
    var referenceObj: WeakReference<Any>? = null
    var reference1: WeakReference<Class<*>>? = null
    var referenceObj1: WeakReference<Any>? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_dex_loader)
    }

    fun Track(view: View?) {
        loadDexClass()
    }

    private fun loadDexClass() {
        val OutputDir = FileUtils.getCacheDir(
            applicationContext
        )
        val dexPath = OutputDir.absolutePath + File.separator + "classLoader.jar"
        val desFile = File(dexPath)
        try {
            if (!desFile.exists()) {
                desFile.createNewFile()
                FileUtils.copyFiles(this, "classLoader.jar", desFile)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        }
        /**
         * 参数1 dexPath：待加载的dex文件路径，如果是外存路径，一定要加上读外存文件的权限
         * 参数2 optimizedDirectory：解压后的dex存放位置，此位置一定要是可读写且仅该应用可读写（安全性考虑），所以只能放在data/data下。
         * 参数3 libraryPath：指向包含本地库(so)的文件夹路径，可以设为null
         * 参数4 parent：父级类加载器，一般可以通过Context.getClassLoader获取到，也可以通过ClassLoader.getSystemClassLoader()取到。
         */
        val classLoader = MyDexClassLoader(
            dexPath, OutputDir.absolutePath, null,
            classLoader
        )
        try {
            // 该方法将Class文件加载到内存时,并不会执行类的初始化,直到这个类第一次使用时才进行初始化.该方法因为需要得到一个ClassLoader对象
            var clz = classLoader.loadClass("com.kxf.javalib.ClassLoaderStaticBean")
            var clzBean = classLoader.loadClass("com.kxf.javalib.ClassLoaderBean")
            Log.d(tag, "加载完class===")
            reference = WeakReference(clz)
            var dexStatic = clz.newInstance()
            referenceObj = WeakReference(dexStatic)
            Log.d(tag, "dex Static===" + dexStatic)
            Log.d(tag, "clz Static classLoader===" + clz.classLoader)

            reference1 = WeakReference(clzBean)
            var dex = clzBean.newInstance()
            referenceObj1 = WeakReference(dex)
            Log.d(tag, "dex===" + dex)
            Log.d(tag, "clz classLoader===" + clzBean.classLoader)
        } catch (e: Exception) {
            e.printStackTrace()
        }

        val thread = Thread {
            Runtime.getRuntime().gc()
            try {
                Thread.sleep(2000)
            } catch (e: InterruptedException) {
                // TODO Auto-generated catch block
                e.printStackTrace()
            }
            println("reference==" + reference?.get())
            println("referenceObj==" + referenceObj?.get())

            println("reference1==" + reference1?.get())
            println("referenceObj1==" + referenceObj1?.get())
        }
        thread.start()
    }
}